package sig

import (
	"WebSvr/modules/common"
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"github.com/astaxie/beego"
)

type SignalHandler func(s os.Signal, arg interface{})

type SignalSet struct {
	m map[os.Signal]SignalHandler
}

func SignalSetNew() *SignalSet {
	ss := new(SignalSet)
	ss.m = make(map[os.Signal]SignalHandler)
	return ss
}

func (set *SignalSet) Register(s os.Signal, handler SignalHandler) {
	if _, found := set.m[s]; !found {
		set.m[s] = handler
	}
}

func (set *SignalSet) Handle(sig os.Signal, arg interface{}) (err error) {
	if _, found := set.m[sig]; found {
		set.m[sig](sig, arg)
		return nil
	} else {
		return fmt.Errorf("No handler available for signal %v", sig)
	}
	panic("won't reach here")
}

func sigHandlerFunc(s os.Signal, arg interface{}) {
	switch s {
	case syscall.SIGINT:
		closeApp("recv syscall.SIGINT")
	case syscall.SIGQUIT:
		closeApp("syscall.SIGQUIT")
	}
}

func closeApp(str string) {
	if !common.GStopFlag {
		beego.Info(str)
		common.GStopFlag = true
		//延时关闭进程
		deferTime := beego.AppConfig.String("deferclose")
		var deferTime_int64 int64
		deferTime_int64, _ = strconv.ParseInt(deferTime, 10, 64)
		if deferTime_int64 == 0 {
			deferTime_int64 = 15
		}
		t := time.Duration(deferTime_int64) * time.Second
		beego.Info(t)
		timer := time.NewTicker(t)
		for {
			select {
			case <-timer.C:
				{
					str := fmt.Sprintf("%s秒时间到,关闭进程", deferTime)
					beego.Info(str)
					command := "./closeApp.sh"
					params := []string{"WebSvr"}
					execCommand(command, params)
				}
			}
		}
	}
}

func execCommand(commandName string, params []string) bool {
	cmd := exec.Command(commandName, params...)

	//显示运行的命令
	fmt.Println(cmd.Args)

	stdout, err := cmd.StdoutPipe()

	if err != nil {
		fmt.Println(err)
		return false
	}

	cmd.Start()

	reader := bufio.NewReader(stdout)

	//实时循环读取输出流中的一行内容
	for {
		line, err2 := reader.ReadString('\n')
		if err2 != nil || io.EOF == err2 {
			break
		}
		beego.Info(line)
	}

	cmd.Wait()
	return true
}

func SignalListen() {
	sigHandler := SignalSetNew()
	sigHandler.Register(syscall.SIGQUIT, sigHandlerFunc)
	sigHandler.Register(syscall.SIGINT, sigHandlerFunc)
	//sigHandler.Register(syscall.SIGUSR2, sigHandlerFunc)
	sigChan := make(chan os.Signal, 10)
	signal.Notify(sigChan)

	for {
		select {
		case sig := <-sigChan:
			err := sigHandler.Handle(sig, nil)
			if err != nil {
				fmt.Printf("[ERROR] unknown signal received: %v\n", sig)
				os.Exit(1)
			}
		default:
			//time.Sleep(time.Duration(1) * time.Second)
		}
	}
}
